<?php
// +----------------------------------------------------------------------
// | OneChat [ 做实用的网站微信内容交互管理平台 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://www.juexin.pro All rights reserved.
// +----------------------------------------------------------------------
// | Author: Tealun Du <tealun@guilins.com> <http://www.tealun.com>
// +----------------------------------------------------------------------

// +----------------------------------------------------------------------
// | 系统配置类函数
// | 一般用于微信公众号的配置设置和检查
// +----------------------------------------------------------------------

/**
 * 处理回复消息类型模板
 *
 * @param string $type 消息类型
 *
 * @return string
 */
function get_wechat_tpl($type) {
    switch ( $type ) {

        case 'text':
            $tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><Content><![CDATA[%s]]></Content><MsgId><![CDATA[%s]]></MsgId></xml>";
            break;
        case 'news':
            $tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><ArticleCount>%s</ArticleCount><Articles>%s</Articles></xml>";
            break;
        case'image':
            $tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><Image><MediaId><![CDATA[%s]]></MediaId></Image></xml>";
            break;
        case'voice':
            $tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><Voice><MediaId><![CDATA[%s]]></MediaId></Voice></xml>";
            break;
        case'music':
            $tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><Music><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><MusicUrl><![CDATA[%s]]></MusicUrl><HQMusicUrl><![CDATA[%s]]></HQMusicUrl><ThumbMediaId><![CDATA[%s]]></ThumbMediaId></Music></xml>";
            break;
        case'video':
            $tpl = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[video]]></MsgType><Video><MediaId><![CDATA[media_id]]></MediaId><Title><![CDATA[title]]></Title><Description><![CDATA[description]]></Description></Video></xml>";
            break;
        case 'service':
            $tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType></xml>";
            break;
        case'setService':
            $tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><TransInfo>     <KfAccount><![CDATA[%s]]></KfAccount></TransInfo></xml>";
            break;
        default:
            $tpl = '';
    }

    return $tpl;
}

/**
 * 获取微信配置项
 *
 * @param bool  $reset  是否重新获取配置项
 *
 * @return array        返回配置数组
 */
function get_wechat_config($reset = false){
    if(S('WechatConfig') && $reset == false){
        return S('WechatConfig');
    }else{
        return save_wechat_config();
    }
}

/**
 * 缓存微信配置项
 * 微信配置项的设置在config表中，以WECHAT开头
 *
 * @return mixed
 */
function save_wechat_config(){

    $Config = M('Config');
    $map = array(
        'name'=>array('like','WECHAT%')
    );

    $res = $Config->where($map)->getField('name,value');
    S('WechatConfig',$res,3600);//缓存配置项，有效期1小时

    return S('WechatConfig');
}

/**
 * 查看是否获得认证
 * @return bool
 */
function check_wechat_rz() {

    $config = get_wechat_config(true);

    /** @var string $value 指定配置项 */
    $value = $config['WECHAT_ACCOUNT_RZ'];

    return $value == 1 ? true : false;
}

/**
 * 查看是否开启多客服
 * @return bool
 */
function check_wechat_service() {
    //通过获取客服列表
    $check = get_wechat_service();
    return is_array($check)?true:false;
}

/**
 * 查看账户类型
 * @return string
 */
function check_wechat_type() {

    $config = get_wechat_config(true);

    /** @var string $value 指定配置项 */
    $value = $config['WECHAT_ACCOUNT_TYPE'];
    switch ( $value ) {
        case '1':
            $type = "服务号";
            break;
        case '2':
            $type = "企业号";
            break;
        default:
            $type = "订阅号";
            break;
    }

    return $type;
}


/**
 * 获取公众账号的accessToken
 *
 * @param bool      $reset  是否墙纸缓存新的access_token
 *
 * @return array            返回accessToken
 */
function get_access_token($reset = false) {
    if($reset == false){
        $accessToken = S('accessToken') ? S('accessToken') : save_access_token();
    }else{
        $accessToken = save_access_token();
    }
    return $accessToken;
}

/**
 * 缓存公众帐号accessToken
 *
 * @return array    返回缓存后的accessToken
 */
function save_access_token() {
    $config = get_wechat_config();
    $appId = $config['WECHAT_APP_ID'];
    $appSecret = $config['WECHAT_APP_SECRET'];
    $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appId . '&secret=' . $appSecret;

    $re = doCurl($url);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);

        echo 'accessToken获取错误：'.$re['errcode'].$re['errmsg'];
        exit;
    }else{
        /* 存储获取到的access_token，有限期为获取到的有限期，正常情况下为 7200 */
        S('accessToken' , $re['access_token'] , $re['expires_in']);

        return S('accessToken');
    }

}

/**
 * 系统故障回复客户消息
 *
 * 客户发送消息后由于系统问题，比如无法正常查询数据库等情况下回复客户出错
 * 一般情况下，如果出现此错误，并非Wechat模块问题，可参考是否正确连接数据库，配置文件是否正确，实例化对象是否正常
 *
 * @param string    $action         出现故障的检测点操作方法
 * @param string    $openId         要回复的客户openid
 * @param string    $clientContent  客户发来的消息
 *
 * @return array                    ['client']用于回复客户，['SUPPORT']用于报告客服
 *
 */
function get_wechat_error($action , $openId , $clientContent) {
    $time = Date('Y-m-d H:i:s' , TIME());
    $client = get_client_info($openId);
    $messge = "亲爱的\"" . $client['nickname'] ? $client['nickname'] :'朋友：';
    $messge .= "\n非常抱歉，貌似系统感冒了…\n此次故障我们已经记录，我们会尽快处理，感谢您的支持。\n<a href='http://" . $_SERVER["HTTP_HOST"] . ">点击进入官网</a>";
    $mailMessge = $time. $client['country'] . $client['province'] . $client['city'] . " 客户“" . $client['nickname'] . "”在发送消息“" . $clientContent . "”时发生故障，事件环节为“" . $action . "”请尽快处理，如果您无法处理该问题，请致电开发人员解决。";

    //返回错误信息，前提是Wechat模块运行正常
    return array(
        'client' => $messge , //发送给客户的
        'SUPPORT' => $mailMessge , //发送给客服的
    );
}


// +----------------------------------------------------------------------
// | 消息交互函数
// | 一般用于微信客户消息的数据构建
// +----------------------------------------------------------------------

/**
 * 构建回复消息数组
 *
 * @param string|array  $content    要回复的数据内容
 * @param string        $type       要回复的消息类型
 *                                      文本(text) 图文(news)  音乐(music) 语音(voice) 链接(url) 客服消息(service)
 *                                      使用service类型标识,传入空字符即可，注意调用本函数的后续流程中要将<MegType>设置为"transfer_customer_service"
 *
 *
 * @return array 返回指定消息类型数据构建后的数组
 */
function set_response_arr($content,$type='text') {

    return array($content , $type);

}


// +----------------------------------------------------------------------
// | 粉丝管理交互函数
// | 一般用于微信客户消息的数据构建
// +----------------------------------------------------------------------

/**
 * 获取粉丝详细信息
 * 通过微信接口获取详细粉丝信息
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839
 *
 * @param string $openId    关注帐号粉丝的openid
 *
 * @return Array
 */
function get_client_info($openId) {

    $url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . get_access_token() . '&openid=' . $openId ;

    $str = doCurl($url);

    return json_decode($str , true);

}

/**
 * 设置微信粉丝备注
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140838
 *
 * @param string    $openid     要设置的客户微信openid
 * @param string    $remark     要设置的备注名
 *
 * @return array
 */
function set_client_remark($openid,$remark){
    $data = array(
        'openid'=>$openid,
        'remark'=>$remark,
    );
    $data = JSON($data);
    $url = 'https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token='.get_access_token();
    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
    return $re;
}

/**
 * 获取关注用户列表
 * 注意，只会返回用户openid，不会获取到客户详细信息
 * 实际调用时，如果关注用户多的情况下，建议不要同时更新客户信息
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140840
 *
 * @param string $nextOpenid    获取开始的openid
 *
 * @return mixed|string
 */
function get_wechat_client($nextOpenid = ''){
    $url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token='. get_access_token();
    if(!empty($nextOpenid)){
        $url .= '&next_openid='.$nextOpenid;
    }
    $re = doCurl($url);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }

    return $re;
}


/**
 * 获取标签的ID
 *
 * @param string $tagName   标签名称
 *
 * @return mixed
 */
function get_tag_id($tagName){
    $tags = get_wechat_tags();
    foreach($tags as $v) {//从标签数组中找匹配的标签
        if ($v['name'] == $tagName) {
            return $v['id'];
            break;
        }
    }

    //无匹配返回原值
    return $tagName;
}

/**
 * 获取标签的名称
 * @param int   $tagid  标签ID
 *
 * @return mixed
 */
function get_tag_name($tagid){

    $tags = get_wechat_tags();
    foreach($tags as $v) {//从标签数组中找匹配的标签
        if ($v['id'] == $tagid) {
            return $v['name'];
            break;
        }
    }

    //无匹配返回原值
    return $tagid;
}


/**
 * 获取标签列表
 * @return mixed
 */
function get_wechat_tags($reset = false){
    if($reset !== false){
        return save_wechat_tags();
    }
    return S('wechatTags')?S('wechatTags'):save_wechat_tags();
}

/**
 * 存储标签列表
 * @return mixed
 */
function save_wechat_tags(){
    $url = 'https://api.weixin.qq.com/cgi-bin/tags/get?access_token='. get_access_token();

    $re = doCurl($url);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
    S('wechatTags',$re['tags']);
    return S('wechatTags');
}

/**
 * 设置标签
 * 详见 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140837
 *
 * @param array  $data      设置的数据
 *                              格式：array('tag'=>array('name'=>name))
 * @param string $action    要进行的操作
 *                              create:创建新标签
 *                              getidlist:查询用户身上的标签
 *                              update:修改标签名称
 *                              delete:删除标签
 *
 * @return array    json解析后的数组
 */
function set_wechat_tag($data,$action='create'){

    $data = JSON($data);
    $url = 'https://api.weixin.qq.com/cgi-bin/tags/'.$action.'?access_token='.get_access_token();

    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
    //创建、更新、删除标签后，重新缓存标签
    if($action != 'getidlist'){
        save_wechat_tags();
    }

    return $re;
}

/**
 * 获取标签下的粉丝列表
 * 详见 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140837
 *
 * @param int       $tagid          标签ID
 * @param string    $nextOpenid     从哪个openid开始
 *
 * @return mixed
 */
function get_tag_openid($tagid,$nextOpenid){
    $data = array(
        "tagid" => $tagid,
        "next_openid"=>$nextOpenid //第一个拉取的OPENID，不填默认从头开始拉取
    );
    $data = JSON($data);
    $url = 'https://api.weixin.qq.com/cgi-bin/user/tag/get?access_token='.get_access_token();

    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);

    if($re['errcode'] != 0){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
    return $re;

}

/**
 * 查询客户身上的标签
 * 详见 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140837
 *
 * @param $openid
 *
 * @return string 返回标签拼接字符串
 */
function get_openid_tags($openid){

    $data['openid']=$openid;
    $re = set_wechat_tag($data,'getidlist');

    return arr2str($re['tagid_list']);
}

/**
 * 客户标签批量操作（打标签和移除标签）
 * 也适用于单个客户，只需要传入只有一个键值的数组就可以
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140837
 *
 * @param array  $openid 客户微信的openid数组 不能超过50个
 * @param string $tagid  标签名
 * @param string $action 批量操作的类型：
 *                        批量打标签：tagging
 *                        批量取消标签：untagging
 *
*@return mixed
 */
function batch_client_tag($openid,$tagid,$action){

    $data['openid_list']=$openid;
    $data['tagid']=$tagid;
    $data = JSON($data);
    $url = 'https://api.weixin.qq.com/cgi-bin/tags/members/batch'.$action.'?access_token='.get_access_token();

    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);

    if($re['errcode'] != 0){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
    return $re;
}


// +----------------------------------------------------------------------
// | 自定义菜单管理交互函数
// | 含自定义默认菜单和个性化菜单
// +----------------------------------------------------------------------

/**
 * 将自定义菜单【默认菜单】发布到微信服务器
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013
 *
 * @param   array       $data   菜单树数组
 * @return bool|mixed
 *
 */
function set_wechat_menu($data){

    $data = JSON($data);
    //POST提交地址
    $url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . get_access_token();

    $str = doCurl($url ,'POST', $data); //提交到自定义菜单更新端口并获得返回数据
    $re =  json_decode($str , true); //将返回的json数据转换为数组形式

    if($re['errcode'] != 0){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }

    return $re;
}

/**
 * 获取微信服务器上的自定义菜单【默认菜单】
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014
 *
 * @return mixed
 */
function get_wechat_menu(){
    $url = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token='.get_access_token();
    $re = doCurl($url);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
        return $re;
}

/**
 * 清空微信服务器上的自定义菜单【默认菜单和个性化菜单】
 * 此操作会删除自定义菜单和所有个性化菜单 !important
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015
 *
 * @return bool|mixed
 */
function del_wechat_menu(){

    $url = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token='.get_access_token();
    $re = doCurl($url);
    $re = json_decode($re,true);

    if($re['errcode'] != 0){
        $re['errmsg'] = get_wechat_response($re['errcode']);
        return $re;
    }else{
        return true;
    }

}

/**
 * 增加个性化菜单【非默认菜单】
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296
 *
 * @param   array $data 增加个性化菜单需要的数据数组，格式参考：
 *
 * @return mixed|string
 */
function add_conditional_menu($data){

    $data = JSON($data);
    $url = 'https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token='.get_access_token();
    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
        return $re;

}

/**
 * 删除个性化菜单【非默认菜单】
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296
 *
 * @param int $menuid   个性化菜单ID 数据格式参考：
 *
 * @return bool|string
 */
function del_conditional_menu($menuid){

    $data = array('menuid'=>$menuid);
    $data = JSON($data);

    $url = 'https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token='.get_access_token();
    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);

    if($re['errcode'] != 0){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
    return $re;
}

/**
 * 测试个性化菜单匹配结果
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296
 *
 * @param string $openid 用于测试的微信号或者openid
 *
 * @return mixed|string
 */
function try_conditional_menu($openid){
    $data = array('user_id'=>$openid);
    $data = JSON($data);
    $url = 'https://api.weixin.qq.com/cgi-bin/menu/trymatch?access_token='.get_access_token();
    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);

    if($re['errcode']){
        $re['errmsg'] = get_wechat_response($re['errcode']);
    }
        return $re;
}

// +----------------------------------------------------------------------
// | 二维码交互函数
// | 创建含参数的二维码用
// +----------------------------------------------------------------------

/**
 * 创建二维码的ticket
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542
 *
 * @param array $sceneArr   获取ticket需要用到的数据
 *
 * @return mixed
 */
function get_qr_ticket($sceneArr){
    //转换POST获取ticket所需的JSON格式
    $content = JSON($sceneArr , true);
    //POST提交地址
    $url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' . get_access_token();
    $ticket = doCurl($url ,'POST', $content); // 执行请求,得到ticket的json回复数据
    $ticket = json_decode($ticket , true);//ticket转换成数组

    if($ticket['errcode']){//查看是否有错误代码
        return false;
    }

    return $ticket['ticket'];
}

/**
 * 获取二维码图片
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433542
 * @param $ticket
 *
 * @return string
 */
function get_qr_code($ticket) {
    if ( is_numeric($ticket) ) {
        $ticket = M('TchatQrcode')->where('`id` = "' . $ticket . '"')->getField('ticket');
    }

    return 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . $ticket;
}

// +----------------------------------------------------------------------
// | 素材函数
// | 短链接、多媒体文件等
// +----------------------------------------------------------------------

/**
 * 短链接功能
 * 详见https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1443433600
 * @param float $long_url
 *        	长链接
 * @return string 如果没有微信短链接接口权限或者不成功，就原样返回长链接，否则返回短链接
 */
function short_url($long_url) {
    $access_token = get_access_token ();
    if (empty ( $access_token )) {
        return $long_url;
    }

    $url = 'https://api.weixin.qq.com/cgi-bin/shorturl?access_token=' . $access_token;

    $data ['action'] = 'long2short';
    $data ['long_url'] = $long_url;

    $res = doCurl($url,'POST',$data);
    $res = json_decode ( $res, true );
    if ($res ['errcode'] == 0) {
        return $res ['short_url'];
    } else {
        return $long_url;
    }
}

/**
 * TODO 创建临时素材
 * 1、对于临时素材，每个素材（media_id）会在开发者上传或粉丝发送到微信服务器3天后自动删除。
 * 2、media_id是可复用的。
 * 3、素材的格式大小等要求与公众平台官网一致。
 *    具体是，图片大小不超过2M，支持png/jpeg/jpg/gif格式；
 *            语音大小不超过5M，长度不超过60秒，支持mp3/amr格式
 * 调用示例（使用curl命令，用FORM表单方式上传一个多媒体文件）：
 * curl -F media=@test.jpg "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738726
 *
 * @param object    $file   要上传的文件
 * @param string    $type   文件的类型 分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb）
 *
 */
function upload_wechat_media($path, $type = 'image') {
    $url = 'http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=' . get_access_token () .'&type='.$type;
    $param ['type'] = $type;
    $param ['media'] = '@' . realpath ( $path );
    $res = post_data ( $url, $param, true );
    if (isset ( $res ['errcode'] ) && $res ['errcode'] != 0) {
        return false;
    }
    return $res ['media_id'];
}
/**
 * 下载临时素材（即下载临时的多媒体文件）
 * 请注意，视频文件不支持https下载，调用该接口需http协议。
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738727
 *
 * @param int   $media_id   临时多媒体文件素材的id
 *
 * @return array
 */
function download_wechat_media($media_id) {
    // 获取图片URL
    $url = 'https://api.weixin.qq.com/cgi-bin/media/get?access_token=' . get_access_token () . '&media_id=' . $media_id;

    $ch = curl_init($url);
    curl_setopt($ch , CURLOPT_HEADER , 0);
    curl_setopt($ch , CURLOPT_NOBODY , 0);    //只取body头
    curl_setopt($ch , CURLOPT_SSL_VERIFYPEER , false);
    curl_setopt($ch , CURLOPT_SSL_VERIFYHOST , false);
    curl_setopt($ch , CURLOPT_RETURNTRANSFER , 1);
    $package = curl_exec($ch);
    $httpinfo = curl_getinfo($ch);
    curl_close($ch);

    return array_merge(array( 'header' => $httpinfo ) , array( 'body' => $package ));
}

/**
 * 存储客户发送的临时素材
 * 有更改，增加一个传入参数$filePath并对此参数进行目录检查，不存在则建立，以解决原代码只能存储在既有目录的问题
 * @author 方倍工作室  <http://www.cnblogs.com/txw1958/>
 *
 * @param string $filePath    存储目录路径
 * @param string $fileName    文件名
 * @param object $fileContent 从微信服务器下载到的文件对象
 *
 * @return bool
 */
function save_wechat_media( $filePath , $fileName , $fileContent){

    if ( !is_dir($filePath) ) {
        mkdir($filePath , 0777 , true);
    }

    $fileName = $filePath . $fileName;
    $local_file = fopen($fileName , 'w');

    if ( $local_file !== false) {
        if ( fwrite($local_file , $fileContent) !== false) {
            fclose($local_file);
            return true;
        }
    }

    return false;

}

function get_meterial_count(){
    $url = 'https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token='.get_access_token();
    $res = doCurl($url);
    $res = json_decode ( $res, true );
    if ($res ['errcode'] == -1) {
        return  get_wechat_response($res['errcode']);
    } else {
        return $res;
    }
}

/**
 * 获取永久素材
 * @param $media_id
 */
function get_material($media_id){
    $url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token='.get_access_token();
    $data = '{"media_id":"'.$media_id.'"}';
    $res = doCurl($url,'POST',$data);
    $res = json_decode ( $res, true );
    if ($res ['errcode']) {
        return  get_wechat_response($res['errcode']);
    } else {
        return $res;
    }
}

/**
 * 获取永久素材列表（批量获取素材列表）
 * @param $type
 * @param $offset
 * @param $count
 */
function batch_get_material($type,$offset,$count){
    $url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token='.get_access_token();
    $data = '{"type":"'.$type.'","offset":'.$offset.',"count":'.$count.'}';
    $res = doCurl($url,'POST',$data);
    $count = S('getMeterial')?:0;
    $count++;
    //var_dump($count);
    S('getMeterial',$count);
    $res = json_decode ( $res, true );
    if ($res ['errcode']) {
        return  get_wechat_response($res['errcode']);
    } else {
        return $res;
    }
}

//TODO 上传永久素材函数
/**
 * @param $file
 * @param string $type  媒体文件类型，分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb）
 */
function add_material($file,$type){
    $url = 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.get_access_token().'&type='.$type;
    switch($type){
        case'image':
            $type = 'image/jpeg';
            $limit = '2048';
            break;
        case'voice':
            $limit = '2048';
            break;
        case'video':
            $limit = '10240';
            break;
        case'thumb':
            $type = 'image/jpeg';
            $limit = '64';
            break;
        default:
            $limit = '64';
            break;
    }
    $pattern = '/\/(\w+\.\w+)$/i';
    preg_match($pattern,$file,$name);

    $file_info = array('filename' => $name[1], //图片名称
        'content-type' => $type, //文件类型
        'filelength' => $limit //图文大小
    );

    $ch1 = curl_init();
    $timeout = 5;
    $real_path = $_SERVER['DOCUMENT_ROOT']. $file;

    //PHP 5.5另外引入了CURL_SAFE_UPLOAD选项，可以强制PHP的cURL模块拒绝旧的@语法，仅接受CURLFile式的文件。5.5的默认值为false，5.6的默认值为true。
    //微信公众号多媒体上传接口返回码出现41005的原因就是不能识别文件.
    if (class_exists ( '\CURLFile' )) {//关键是判断curlfile,官网推荐php5.5或更高的版本使用curlfile来实例文件
        $real_path = new \CURLFile ( $real_path, 'image/jpeg' );
    } else {
        $real_path = '@' . $real_path;
    }

    $data = array("media" => $real_path, 'form-data' => $file_info);
    curl_setopt($ch1, CURLOPT_URL, $url);
    curl_setopt($ch1, CURLOPT_POST, 1);
    curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch1, CURLOPT_POSTFIELDS, $data);
    $result = curl_exec($ch1);
    curl_close($ch1);

    $result = json_decode($result, true);
    if($result['errcode']){
        return false;
    }
    return $result['media_id'];
}

/**
 * 删除永久素材
 * @param $media_id
 * @return int|string
 */
function delete_material($media_id){
    $url = 'https://api.weixin.qq.com/cgi-bin/material/del_material?access_token='.get_access_token();

    $data ['media_id'] = $media_id;
    $data = JSON($data);
    $res = doCurl($url,'POST',$data);
    $res = json_decode ( $res, true );
    if ($res ['errcode'] == 0) {
        return 0;
    } else {
        return  get_wechat_response($res['errcode']);;
    }
}

/**
 * @param string $data json格式的数据
 */
function add_news($articles){
    $url = 'https://api.weixin.qq.com/cgi-bin/material/add_news?access_token='.get_access_token();

    foreach ($articles as &$item){
        foreach ($item as $key => $val){
            if ($key == 'content'){
                $item[$key] = htmlspecialchars(str_replace("\"", "'", $val));
            }
        }
    }

    $data = array(
        "articles"=>$articles
    );

    $data = JSON($data);
    $res = doCurl($url,'POST',$data);
    $res = json_decode ( $res, true );
    if ($res ['errcode']) {
        return $res ['errcode'];
    } else {
        return  $res ["media_id"];
    }
}

function get_news(){

}

function update_news(){

}

function uploading_content_img($pic){
    $url = 'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token='.get_access_token();

    $pattern = '/\/(\w+\.(?:png|jpg))$/i';
    preg_match($pattern,$pic,$name);
    $file_info = array('filename' => $name[1], //图片名称
        'content-type' => 'image/jpeg', //文件类型
        'filelength' => 1024 //图文大小
    );

    $ch1 = curl_init();
    $timeout = 5;
    $real_path = $_SERVER['DOCUMENT_ROOT']. $pic;

    //PHP 5.5另外引入了CURL_SAFE_UPLOAD选项，可以强制PHP的cURL模块拒绝旧的@语法，仅接受CURLFile式的文件。5.5的默认值为false，5.6的默认值为true。
    //微信公众号多媒体上传接口返回码出现41005的原因就是不能识别文件.
    if (class_exists ( '\CURLFile' )) {//关键是判断curlfile,官网推荐php5.5或更高的版本使用curlfile来实例文件
        $real_path = new \CURLFile ( $real_path, 'image/jpeg' );
    } else {
        $real_path = '@' . $real_path;
    }

    $data = array("media" => $real_path, 'form-data' => $file_info);
    curl_setopt($ch1, CURLOPT_URL, $url);
    curl_setopt($ch1, CURLOPT_POST, 1);
    curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch1, CURLOPT_POSTFIELDS, $data);
    $result = curl_exec($ch1);
    curl_close($ch1);

    $result = json_decode($result, true);
    if(!$result['url']){
        return false;
    }
    return $result['url'];

}

// 以POST方式提交数据
function post_data($url, $param, $is_file = false, $return_array = true) {
    if (! $is_file && is_array ( $param )) {
        $param = JSON ( $param );
    }
    if ($is_file) {
        $header [] = "content-type: multipart/form-data; charset=UTF-8";
    } else {
        $header [] = "content-type: application/json; charset=UTF-8";
    }

    $ch = curl_init ();
    curl_setopt ( $ch, CURLOPT_URL, $url );
    curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
    curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
    curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
    curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header );
    curl_setopt ( $ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)' );
    curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
    curl_setopt ( $ch, CURLOPT_AUTOREFERER, 1 );
    curl_setopt ( $ch, CURLOPT_POSTFIELDS, $param );
    curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
    $res = curl_exec ( $ch );

    curl_close ( $ch );

    $return_array && $res = json_decode ( $res, true );

    return $res;
}


// +----------------------------------------------------------------------
// | 模版消息交互函数
// | 模版消息设置和发送用到的函数
// +----------------------------------------------------------------------

/**
 * 群发消息
 * @param array     $tag        要发送到的客户分组或openid列表
 * @param array     $message    要发送的消息体
 * @param string    $type       预览的素材类型
 *                               图文:"mpnews" 、文本:"text"、语音：:"voice"
 *                               图片:"image" 、视频:"mpvideo" 、卡券:"wxcard"
 */
function mass_send($touser,$message,$type){

    //判断是否是根据标签发送
    if(!is_array($touser)){
        $url='https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token='.get_access_token();
        $data['filter'] = array(
            'is_to_all'=>false,//todo 这是检测是否放到公众号历史消息中，后期改为客户选择
            'tag_id'=>(int)$touser
        );
    }else{
        $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token='.get_access_token();
        $data['touser'] =$touser;
    }

    switch($type){
        case 'mpnews':
            $data['mpnews'] = array('media_id'=>$message);
            $data['send_ignore_reprint'] = 0;
            break;
        case 'text':
            $data['text']= array('content'=>$message);
            break;
        case 'mpvideo':
            //请注意，此处视频的media_id需通过POST请求到下述接口特别地得到：POST数据如下（此处media_id需通过基础支持中的上传下载多媒体文件来得到）：
            $data['mpvideo'] = array(
                'media_id'=> get_mass_upload_video($message['media_id'],$message['title'],$message['description']),
                'title'=>$message['title'],
                'description'=>$message['description']
            );
            $data['msgtype'] = "mpvideo";
            break;
        case 'wxcard':
            $data[$type]= array('card_id'=>$message);
            break;
        default:
            $data[$type] = array('media_id'=>$message);
    }
    $data['msgtype'] = $type;

    $data = JSON($data);
    $res = doCurl($url,'POST',$data);
    $res = json_decode ( $res, true );
    if ($res ['errcode']) {
        //$res['errmsg'] = get_wechat_response($res['errcode']);
    }
        return  $res;
}

/**
 * 群发预览
 * @param string    $mediaId    预览的素材media_id
 * @param string    $type       预览的素材类型
 *                               图文:"mpnews" 、文本:"text"、语音：:"voice"
 *                               图片:"image" 、视频:"mpvideo" 、卡券:"wxcard"
 * @param string    $towxname   发送到的微信号
 * @param string    $openId     发送到的微信openid，与towxname二选一，都写微信平台优先取用towxname
 */
function mass_preview($message,$type,$towxname,$openId=''){
    $url='https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token='.get_access_token();

    if($towxname){
        $data['towxname']=$towxname;
    }elseif(!empty($openId)){
        $data['touser']=$openId;
    }else{
        return '请指定预览的微信号。';
    }

    switch($type){
        case 'text':
            $data[$type]=array('content'=>$message);
            break;
        case 'wxcard':
            //说明：卡券需要特殊的数据组合
            $data[$type]=array(
                'card_id'=>$message['card_id'],
                'card_ext'=>$message['card_ext']
                );
            break;
        default:
            $data[$type]=array('media_id'=>$message);
    }
    $data['msgtype']=$type;

    $data = JSON($data);
    $res = doCurl($url,'POST',$data);
    $res = json_decode ( $res, true );
    if ($res ['errcode']) {
        return get_wechat_response($res['errcode']);
    } else {
        return  0;
    }
}

function get_mass_upload_video($media_id,$title,$description){
    $url = 'https://api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token='.get_access_token();
    $data = array(
        'media_id'=>$media_id,
        'title'=>$title,
        'description'=>$description
    );
    //TODO will done this later
}
// +----------------------------------------------------------------------
// | 模版消息交互函数
// | 模版消息设置和发送用到的函数
// +----------------------------------------------------------------------

/**
 * 设置微信服务器行业属性
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
 *
 * @param array $data 要设置的行业ID
 *                    array(
 *                           "industry_id1"=>1,
 *                          "industry_id2"=>4
 *                    )
 */
function set_industry($data=array()){
    $url = 'https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=' . get_access_token ();
    $data = JSON($data);
    doCurl($url,'POST',$data);
    //fixme 该接口文档没有说明返回数据 可尝试下看看返回结果
}

/**
 * 获取设置的行业信息
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
 *
 * @return mixed
 */
function get_industry(){
    $url = 'https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=' . get_access_token ();
    $re = doCurl($url);
    return json_decode($re,true);
}

/**
 * 获取所有行业模版
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
 *
 * @return array 返回数据说明：
 *            template_list=>(
 *                  array(
 *                     template_id    模板ID
 *                     title    模板标题
 *                     primary_industry    模板所属行业的一级行业
 *                      deputy_industry    模板所属行业的二级行业
 *                      content    模板内容
 *                      example    模板示例
 *                   ),
 *                  array(
 *                   ...........
 *                  ),.......
 *               )
 */
function get_template_list(){
    $url = 'https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=' . get_access_token ();
    $re = doCurl($url);
    return json_decode($re,true);
}

/**
 * 获取模版ID
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
 *
 * @param   string $templateIdShort 模板库中模板的编号，有“TM**”和“OPENTMTM**”等形式
 *
 * @return mixed
 */
function get_template_id($templateIdShort){
    $url = 'https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=' . get_access_token ();
    $data['template_id_short']=$templateIdShort;
    $data = JSON($data);
    $re = doCurl($url,'POST',$data);
    return json_decode($re,true);
}

/**
 * 删除模版消息
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
 * @param  string   $template_id  公众帐号模板消息ID
 *
 * @return mixed
 */
function delete_template($template_id){

    $data['template_id']=$template_id;
    $data = JSON($data);
    $url = 'https://api,weixin.qq.com/cgi-bin/template/del_private_template?access_token=' . get_access_token ();

    $re = doCurl($url,'POST',$data);
    return json_decode($re,true);
}

/**
 * 发送模版消息
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277
 *
 * @param string    $openid         模版消息接收用户openid
 * @param string    $templateId     模版ID
 * @param array     $data           模版内替换标签数据
 *
 * @return bool|string
 */
function send_template_message($openid,$templateId,$data){
    $url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' . get_access_token ();
    $data = array(
        'touser'=>$openid,
        'template_id'=>$templateId,
        'url'=>$url,
        'data'=>$data
    );
    $data = JSON($data);
    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);
    //判断是否发送成功，成功返回消息ID，不成功返回false
    if($re['errcode'] != 0){
        return false;
    }else{
        return $re['msgid'];
    }
}

// +----------------------------------------------------------------------
// | 多客服函数
// | 客服帐号的设置等函数
// +----------------------------------------------------------------------

/**
 * 获取客服帐号列表
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547
 *
 * @return mixed|string
 */
function get_wechat_service(){
    $url = 'https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token='. get_access_token ();
    $re = doCurl($url);
    $re = json_decode($re,true);
    //判断是否发送成功，成功返回消息ID，不成功返回false
    if(!$re['errcode']){
        return $re;
    }else{
        return get_wechat_response($re['errcode']);
    }
}

/**
 * 获取在线客服帐号列表
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547
 *
 * @return mixed|string
 */
function get_wechat_online_service(){
    $url = 'https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token='. get_access_token ();
    $re = doCurl($url);
    $re = json_decode($re,true);
    //判断是否发送成功，成功返回消息ID，不成功返回false
    if(!$re['errcode']){
        return $re;
    }else{
        return get_wechat_response($re['errcode']);
    }
}

/**
 *客服设置接口
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547
 *
 * @param   array     $service    客服帐号数组 array(
 *                                     "kf_account" => "test1@test",
 *                                     "nickname" => "客服1",
 *                                     "password" => "pswmd5",
 *                                     )
 * @param   string    $action     需要执行的操作
 *                                     默认是添加add
 *                                     更新传入update
 *                                     删除传入del
 *
*@return mixed
 */
function set_wechat_service($service,$action = 'add'){
    $url = 'https://api.weixin.qq.com/customservice/kfaccount/'.$action.'?access_token=' . get_access_token ();
    $service = JSON($service);
    $re = doCurl($url,'POST',$service);
    $re = json_decode($re,true);
    if($re['errcode'] == 0){
        return true;
    }else{
        return get_wechat_response($re['errcode']);
    }
}

/**
 * TODO 设置客服帐号的头像
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547
 *
 * @param int   $pic  头像id
 * @param $serviceAccount 要设置的客服帐号
 */
function set_wechat_service_headImg($pic,$serviceAccount){

    $url='http://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=' . get_access_token ().'&kf_account='.$serviceAccount;

}

/**
 * 发送客服消息
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547
 *
 * 只能是发给48小时内有互动的粉丝用户:
 * 1、用户发送信息
 * 2、点击自定义菜单（仅有点击推事件、扫码推事件、扫码推事件且弹出“消息接收中”提示框这3种菜单类型是会触发客服接口的）
 * 3、关注公众号
 * 4、扫描二维码
 * 5、支付成功
 * 6、用户维权
 *
 * @param string    $openid     接收消息的客户openid
 * @param string    $msgType    消息类型：（
 *                                      文本消息：text
 *                                      图片消息：image
 *                                      语音消息：voice
 *                                      视频消息：video
 *                                      音乐消息：music
 *                                      图文消息点击跳转到外链：news
 *                                      图文消息点击跳转到图文消息页面：mpnews
 *                                      卡券：wxcard
 *                                  ）
 * @param array     $message    消息数据
 * @param string    $kfAccount  指定客服帐号
 *
 *@return bool|string
 */
function send_wechat_message($openid,$msgType,$message,$kfAccount=''){

    //构建数据
    $data = array(
        'touser'=>$openid,
        'msgtype'=>$msgType,
        $msgType=>$message
    );

    //指定客服
    if(!empty($kfAccount)){
        $data['kf_account']=$kfAccount;
    }

    $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='. get_access_token ();

    $re = doCurl($url,'POST',$data);
    $re = json_decode($re,true);
    if($re['errcode'] == 0){
        return true;
    }else{
        return get_wechat_response($re['errcode']);
    }
}


// +----------------------------------------------------------------------
// | 其他函数
// +----------------------------------------------------------------------

/**
 * 返回微信回复的错误信息
 * 详见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433747234
 *
 * 微信错误代码随时都会更新，本次代码更新基于截止日期20161116
 *
 * @param int $errcode string 出错的代码编号
 *
 * @return string
 */
function get_wechat_response($errcode) {
    $statusArr = array(
        '-1'=>'系统繁忙，此时请开发者稍候再试',
        '0'=>'请求成功',
        '40001'=>'获取 access_token 时 AppSecret 错误，或者 access_token 无效。请开发者认真比对 AppSecret 的正确性，或查看是否正在为恰当的公众号调用接口',
        '40002'=>'不合法的凭证类型',
        '40003'=>'不合法的 OpenID ，请开发者确认 OpenID （该用户）是否已关注公众号，或是否是其他公众号的 OpenID',
        '40004'=>'不合法的媒体文件类型',
        '40005'=>'不合法的文件类型',
        '40006'=>'不合法的文件大小',
        '40007'=>'不合法的媒体文件 id',
        '40008'=>'不合法的消息类型',
        '40009'=>'不合法的图片文件大小',
        '40010'=>'不合法的语音文件大小',
        '40011'=>'不合法的视频文件大小',
        '40012'=>'不合法的缩略图文件大小',
        '40013'=>'不合法的 AppID ，请开发者检查 AppID 的正确性，避免异常字符，注意大小写',
        '40014'=>'不合法的 access_token ，请开发者认真比对 access_token 的有效性（如是否过期），或查看是否正在为恰当的公众号调用接口',
        '40015'=>'不合法的菜单类型',
        '40016'=>'不合法的按钮个数',
        '40017'=>'不合法的按钮类型',
        '40018'=>'不合法的按钮名字长度',
        '40019'=>'不合法的按钮 KEY 长度',
        '40020'=>'不合法的按钮 URL 长度',
        '40021'=>'不合法的菜单版本号',
        '40022'=>'不合法的子菜单级数',
        '40023'=>'不合法的子菜单按钮个数',
        '40024'=>'不合法的子菜单按钮类型',
        '40025'=>'不合法的子菜单按钮名字长度',
        '40026'=>'不合法的子菜单按钮 KEY 长度',
        '40027'=>'不合法的子菜单按钮 URL 长度',
        '40028'=>'不合法的自定义菜单使用用户',
        '40029'=>'无效的 oauth_code',
        '40030'=>'不合法的 refresh_token',
        '40031'=>'不合法的 openid 列表',
        '40032'=>'不合法的 openid 列表长度',
        '40033'=>'不合法的请求字符，不能包含 \uxxxx 格式的字符',
        '40035'=>'不合法的参数',
        '40038'=>'不合法的请求格式',
        '40039'=>'不合法的 URL 长度',
        '40048'=>'无效的url',
        '40050'=>'不合法的分组 id',
        '40051'=>'分组名字不合法',
        '40060'=>'删除单篇图文时，指定的 article_idx 不合法',
        '40117'=>'分组名字不合法',
        '40118'=>'media_id 大小不合法',
        '40119'=>'button 类型错误',
        '40120'=>'子 button 类型错误',
        '40121'=>'不合法的 media_id 类型',
        '40125'=>'无效的appsecret',
        '40132'=>'微信号不合法',
        '40137'=>'不支持的图片格式',
        '40155'=>'请勿添加其他公众号的主页链接',
        '40163'=>'oauth_code已使用',
        '41001'=>'缺少 access_token 参数',
        '41002'=>'缺少 appid 参数',
        '41003'=>'缺少 refresh_token 参数',
        '41004'=>'缺少 secret 参数',
        '41005'=>'缺少多媒体文件数据',
        '41006'=>'缺少 media_id 参数',
        '41007'=>'缺少子菜单数据',
        '41008'=>'缺少 oauth code',
        '41009'=>'缺少 openid',
        '42001'=>'access_token 超时，请检查 access_token 的有效期，请参考基础支持 - 获取 access_token 中，对 access_token 的详细机制说明',
        '42002'=>'refresh_token 超时',
        '42003'=>'oauth_code 超时',
        '42007'=>'用户修改微信密码， accesstoken 和 refreshtoken 失效，需要重新授权',
        '43001'=>'需要 GET 请求',
        '43002'=>'需要 POST 请求',
        '43003'=>'需要 HTTPS 请求',
        '43004'=>'需要接收者关注',
        '43005'=>'需要好友关系',
        '43019'=>'需要将接收者从黑名单中移除',
        '44001'=>'多媒体文件为空',
        '44002'=>'POST 的数据包为空',
        '44003'=>'图文消息内容为空',
        '44004'=>'文本消息内容为空',
        '45001'=>'多媒体文件大小超过限制',
        '45002'=>'消息内容超过限制',
        '45003'=>'标题字段超过限制',
        '45004'=>'描述字段超过限制',
        '45005'=>'链接字段超过限制',
        '45006'=>'图片链接字段超过限制',
        '45007'=>'语音播放时间超过限制',
        '45008'=>'图文消息超过限制',
        '45009'=>'接口调用超过限制',
        '45010'=>'创建菜单个数超过限制',
        '45011'=>'API 调用太频繁，请稍候再试',
        '45015'=>'回复时间超过限制',
        '45016'=>'系统分组，不允许修改',
        '45017'=>'分组名字过长',
        '45018'=>'分组数量超过上限',
        '45047'=>'客服接口下行条数超过上限',
        '45064'=>'创建菜单包含未关联的小程序',
        '45065'=>'相同 clientmsgid 已存在群发记录，返回数据中带有已存在的群发任务的 msgid',
        '45066'=>'相同 clientmsgid 重试速度过快，请间隔1分钟重试',
        '45067'=>'clientmsgid 长度超过限制',
        '46001'=>'不存在媒体数据',
        '46002'=>'不存在的菜单版本',
        '46003'=>'不存在的菜单数据',
        '46004'=>'不存在的用户',
        '47001'=>'解析 JSON/XML 内容错误',
        '48001'=>'api 功能未授权，请确认公众号已获得该接口，可以在公众平台官网 - 开发者中心页中查看接口权限',
        '48002'=>'粉丝拒收消息（粉丝在公众号选项中，关闭了 “ 接收消息 ” ）',
        '48004'=>'api 接口被封禁，请登录 mp.weixin.qq.com 查看详情',
        '48005'=>'api 禁止删除被自动回复和自定义菜单引用的素材',
        '48006'=>'api 禁止清零调用次数，因为清零次数达到上限',
        '48008'=>'没有该类型消息的发送权限',
        '50001'=>'用户未授权该 api',
        '50002'=>'用户受限，可能是违规后接口被封禁',
        '50005'=>'用户未关注公众号',
        '61451'=>'参数错误 (invalid parameter)',
        '61452'=>'无效客服账号 (invalid kf_account)',
        '61453'=>'客服帐号已存在 (kf_account exsited)',
        '61454'=>'客服帐号名长度超过限制 ( 仅允许 10 个英文字符，不包括 @ 及 @ 后的公众号的微信号 )(invalid   kf_acount length)',
        '61455'=>'客服帐号名包含非法字符 ( 仅允许英文 + 数字 )(illegal character in     kf_account)',
        '61456'=>'客服帐号个数超过限制 (10 个客服账号 )(kf_account count exceeded)',
        '61457'=>'无效头像文件类型 (invalid   file type)',
        '61450'=>'系统错误 (system error)',
        '61500'=>'日期格式错误',
        '63001'=>'部分参数为空',
        '63002'=>'无效的签名',
        '65301'=>'不存在此 menuid 对应的个性化菜单',
        '65302'=>'没有相应的用户',
        '65303'=>'没有默认菜单，不能创建个性化菜单',
        '65304'=>'MatchRule 信息为空',
        '65305'=>'个性化菜单数量受限',
        '65306'=>'不支持个性化菜单的帐号',
        '65307'=>'个性化菜单信息为空',
        '65308'=>'包含没有响应类型的 button',
        '65309'=>'个性化菜单开关处于关闭状态',
        '65310'=>'填写了省份或城市信息，国家信息不能为空',
        '65311'=>'填写了城市信息，省份信息不能为空',
        '65312'=>'不合法的国家信息',
        '65313'=>'不合法的省份信息',
        '65314'=>'不合法的城市信息',
        '65316'=>'该公众号的菜单设置了过多的域名外跳（最多跳转到 3 个域名的链接）',
        '65317'=>'不合法的 URL',
        '87009'=>'无效的签名',
        '9001001'=>'POST 数据参数不合法',
        '9001002'=>'远端服务不可用',
        '9001003'=>'Ticket 不合法',
        '9001004'=>'获取摇周边用户信息失败',
        '9001005'=>'获取商户信息失败',
        '9001006'=>'获取 OpenID 失败',
        '9001007'=>'上传文件缺失',
        '9001008'=>'上传素材的文件类型不合法',
        '9001009'=>'上传素材的文件尺寸不合法',
        '9001010'=>'上传失败',
        '9001020'=>'帐号不合法',
        '9001021'=>'已有设备激活率低于 50% ，不能新增设备',
        '9001022'=>'设备申请数不合法，必须为大于 0 的数字',
        '9001023'=>'已存在审核中的设备 ID 申请',
        '9001024'=>'一次查询设备 ID 数量不能超过 50',
        '9001025'=>'设备 ID 不合法',
        '9001026'=>'页面 ID 不合法',
        '9001027'=>'页面参数不合法',
        '9001028'=>'一次删除页面 ID 数量不能超过 10',
        '9001029'=>'页面已应用在设备中，请先解除应用关系再删除',
        '9001030'=>'一次查询页面 ID 数量不能超过 50',
        '9001031'=>'时间区间不合法',
        '9001032'=>'保存设备与页面的绑定关系参数错误',
        '9001033'=>'门店 ID 不合法',
        '9001034'=>'设备备注信息过长',
        '9001035'=>'设备申请参数不合法',
        '9001036'=>'查询起始值 begin 不合法'
    );
        return $statusArr[$errcode];
}